/**
 * 函数重载
 * 函数重载或者方法重载适用于某个功能一样，但是细节有不一样
 * 比如说一个函数有多个参数，每一个参数代表不通意义 你个时候就可用使用函数重载 
 * 
 */

type MessageType = 'Image' | 'audio' | 'video' | string;
type Message = {
  id: number;
  type: MessageType;
  sendMessage: string;
};

// message:Array<Message>  同等下面
let messageList: Message[] = [
  {
    id: 1,
    type: 'video',
    sendMessage: '视频视频',
  },
  {
    id: 2,
    type: 'audio',
    sendMessage: '我是消息',
  },
  {
    id: 3,
    type: 'video',
    sendMessage: '视频视频',
  },

  {
    id: 4,
    type: 'msg',
    sendMessage: 'msgmsh',
  },
  {
    id: 5,
    type: 'Image',
    sendMessage: '图片图片',
  },
];


// 不使用函数重载
//使用联合数据类型

function getMessage(
  value: number | MessageType
): Message | Array<Message> | undefined {
  if (typeof value === 'number') {
    // find 查找数据对应得某一条 返回翻个
    return messageList.find((tyep) => value === tyep.id);
  } else {
    // 返回的是数组
    return messageList.filter((tyep) => tyep.type === value);
  }
}

// console.log(getMessage('video'));

// document.getElementById  在tsconfig 中的lib 中配置了DOM 所以不会报错

// 现在需求是 可以找返回的具体某一个字段
// getMessage('video').sendMessage  类型“Message | Message[]”上不存在属性“sendMessage”。类型“Message[]”上不存在属性“sendMessage”

// 使用联合类型转换 把getMessage返回类型转化为 Message 这里是上面定义得
// 这里调用方法需要传递 number 类型得 因为find 返回得是一个对象  filter 返回的是一个数组
// let msg = (<Message>getMessage(1)).sendMessage;
// console.log(msg);



// 函数重载
/**
 *  函数重载的定义 
 *  规则一：一个或多个签名组合叫做函数重载
 *  规则二：外部调用函数重载时，稚嫩调用重载的前面 （函数体前面的叫做签名）不能够调用调用使用的函数签名（这个是TS规定的）
 *  规则三：调用函数重载时会根据传递的参数来判定调用的那个函数
 *  规则四：只有一个函数体吗，只有实现签名配备课函数体，所有重载签名签名只有签名，没有配置函数体
 * 
 */
function loadMessage(value: number): Message; // 重载签名有多个
function loadMessage(value: MessageType): Message[];// 重载签名
// function loadMessage(value:string):Message[] | Message |undefined{ // 第一个重载函数会报错 ，因为产书限定是 string （出错规则是根基第一个签名来匹配参数）
// function loadMessage(value:number):Message[] | Message |undefined{ // 第二个重载函数会报错 ，因为产书限定是 string （出错规则是根基第一个签名来匹配参数）
function loadMessage(value: string | number): Message[] | Message | undefined { // 正确
  if (typeof value === 'number') {
    // find 查找数据对应得某一条 返回翻个
    return messageList.find((tyep) => value === tyep.id);
  } else {
    // 返回的是数组
    return messageList.filter((tyep) => tyep.type === value);
  }
}
// 按住ctrl + 鼠标左键会定位到 直接对应类型的函数签名

//此函数返回的 Message 数据类型 所有可通过点来获取值
loadMessage(1).sendMessage;

// 此处返回的是Message[] 数据类型 所有能调用数组的所有方法
const infoMas = loadMessage('video');
infoMas.forEach(i => { console.log(i) })


//============================函数重载签名时候 多个参数不一致时==============================




function newMessage(value: number): Message; // 重载签名有多个
function newMessage(value: MessageType, pageCont: number): Message[];// 重载签名
// function newMessage(value:string|number,pageCont:number = 1):Message[] | Message |undefined{ // 正确

// function newMessage(value:string|number,pageCont?:number):Message[] | Message |undefined{ // 正确
function newMessage(value: string | number, pageCont: number = 1) {  // 这个可用省略返回数据类型，这里会进行类型推断，（PS 我猜这里应该是上面的重载签名有返回类型吧）
  if (typeof value === 'number') {
    // find 查找数据对应得某一条 返回翻个
    return messageList.find((tyep) => value === tyep.id);
  } else {
    // 返回的是数组
    return messageList.filter((tyep) => tyep.type === value).splice(0, pageCont)
  }
}
// 按住ctrl + 鼠标左键会定位到 直接对应类型的函数签名

//此函数返回的 Message 数据类型 所有可通过点来获取值
loadMessage(1).sendMessage;

// 此处返回的是Message[] 数据类型 所有能调用数组的所有方法
const infoMasnew = newMessage('video', 2);
infoMas.forEach(i => { console.log(i) })


// unknown  是所有内=类型的父累  any 是子类

// let x:number =0;
// let y:any = x;

// let z:any=3
// let k:number = z;

// let a: unknown=3
// //不能将类型“unknown”分配给类型“number”
// let b:number = a